﻿/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is BarocStudio.
*
* The Initial Developer of the Original Code is Kevin Ortman.
*
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using BarocLanguage.Tagger;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Utilities;

namespace BarocLanguage.Classification
{
    // ReSharper disable RedundantDefaultFieldInitializer
    [Export(typeof(ITaggerProvider))]
    [ContentType(BarocConstants.ContentType)]
    [TagType(typeof(ClassificationTag))]
    internal sealed class BarocClassifierProvider : ITaggerProvider
    {

        [Export]
        [Name("Baroc")]
        [BaseDefinition("code")]
        internal static ContentTypeDefinition BarocContentType = null;

        [Export]
        [FileExtension(".baroc")]
        [ContentType(BarocConstants.ContentType)]
        internal static FileExtensionToContentTypeDefinition BarocFileType = null;

        [Import]
        internal IClassificationTypeRegistryService ClassificationTypeRegistry = null;

        [Import]
        internal IBufferTagAggregatorFactoryService aggregatorFactory = null;

        public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag
        {

            ITagAggregator<BarocTokenTag> BarocTagAggregator =
                                            aggregatorFactory.CreateTagAggregator<BarocTokenTag>(buffer);

            return new BarocClassifier(buffer, BarocTagAggregator, ClassificationTypeRegistry) as ITagger<T>;
        }
    }

    internal sealed class BarocClassifier : ITagger<ClassificationTag>
    {
        readonly ITagAggregator<BarocTokenTag> _aggregator;
        readonly IDictionary<BarocTokenTypes, IClassificationType> _BarocTypes;

        internal BarocClassifier(ITextBuffer buffer,
                               ITagAggregator<BarocTokenTag> BarocTagAggregator,
                               IClassificationTypeRegistryService typeService)
        {
            _aggregator = BarocTagAggregator;
            _BarocTypes = new Dictionary<BarocTokenTypes, IClassificationType>();
            _BarocTypes[BarocTokenTypes.Text] = typeService.GetClassificationType(BarocConstants.ClassificationTypes.BarocText);
            _BarocTypes[BarocTokenTypes.Keyword] = typeService.GetClassificationType(BarocConstants.ClassificationTypes.BarocKeyword);
            _BarocTypes[BarocTokenTypes.Comment] = typeService.GetClassificationType(BarocConstants.ClassificationTypes.BarocComment);
            _BarocTypes[BarocTokenTypes.Identifier] = typeService.GetClassificationType(BarocConstants.ClassificationTypes.BarocIdentifier);
            _BarocTypes[BarocTokenTypes.String] = typeService.GetClassificationType(BarocConstants.ClassificationTypes.BarocString);
            _BarocTypes[BarocTokenTypes.Number] = typeService.GetClassificationType(BarocConstants.ClassificationTypes.BarocNumber);
        }

        public event EventHandler<SnapshotSpanEventArgs> TagsChanged
        {
            add { }
            remove { }
        }

        public IEnumerable<ITagSpan<ClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans)
        {
            foreach (var tagSpan in _aggregator.GetTags(spans))
            {
                var tagSpans = tagSpan.Span.GetSpans(spans[0].Snapshot);
                yield return new TagSpan<ClassificationTag>(tagSpans[0], new ClassificationTag(_BarocTypes[tagSpan.Tag.type]));
            }
        }
    }

    // ReSharper restore RedundantDefaultFieldInitializer


}
